/*
	Roberto Andrino 12413
	Ivan Concua 12352
	Algoritmos y estructuras de datos
	SetMain.java
	Programa principal que usa lo que provee el Java Collections Framework para trabajar con Sets.
	Instrucciones de uso: El usuario escoje la implementacion de Set que desea usar. Con la clase
	SetFactory se usa el Factory design para devolver objetos de la implementacion escogida por
	el usuario. Despues, el usuario debe agregar nombres de desarrolladores e indicar en que ambiente
	trabajaron esas personas a traves de un menu. Cada nombre se puede agregar solo una vez a cada
	conjunto. Finalmente, aparece un menu donde se contestan varias preguntas acerca de los conjuntos
	de desarrolladores.
*/

import java.util.*; // se importa lo necesario para usar Sets

public class SetMain
{
	public static void main(String[] args)
	{
		// se crea la Factory que devuelve implementaciones de Set
		// Los objetos Set se inicializan para evitar errores, pero pueden
		// cambiar de implementacion segun escoja el usuario
		SetFactory<String> setFactory = new SetFactory<String>();
		Set<String> conjuntoJava = new HashSet<String>();
		Set<String> conjuntoWeb = new HashSet<String>();
		Set<String> conjuntoCel = new HashSet<String>();
		Scanner teclado = new Scanner(System.in);
		boolean ciclo = true;
		boolean ciclo2 = true;
		
		while(ciclo)
		{
			System.out.print("\n1.HashSet\n2.TreeSet\n3.LinkedHashSet\nQue tipo de SET quiere usar? ");
			String option = teclado.nextLine();
			
			if(option.equals("1") || option.equals("2") || option.equals("3"))
			// se le pide una implementacion especifica al Factory, y cada objeto
			// Set usa esa implementacion
			{
				conjuntoJava = setFactory.getSet(option);
				conjuntoWeb = setFactory.getSet(option);
				conjuntoCel = setFactory.getSet(option);
				ciclo = false;
			}
				
			else
				System.out.println("Error: opcion invalida");
		}
		
		// para indicar la implementacion se usara
		System.out.println("Se usara una implementacion de set de clase " + conjuntoJava.getClass());
		
		while(!ciclo)
		{
			String nombre = ""; // nombre del desarrollador
			ciclo2 = true;
			
			while(nombre.equals(""))
			{
				System.out.print("\nIngrese el nombre de un desarrollador: ");
				nombre = teclado.nextLine();
				
				if(nombre.equals("")) // no se permite que no se ingrese un nombre
					System.out.println("Error: nombre invalido");
			}
			
			while(ciclo2)
			{
				System.out.println("\nIndique en que ambientes " + nombre + " ha desarrollado");
				System.out.println("1.Java\n2.Web\n3.Celulares\n4.Agregar otro nombre\n5.Finalizar");
				String option2 = teclado.nextLine();
				
				// El desarrollador se agrega a los conjuntos de desarrolladores que indique el usuario 
				// por medio del menu. Cada vez que el usuario seleccione un conjunto donde agregarlo se
				// revisa que el desarrollador no este ya contenido en ese conjunto.
				if(option2.equals("1"))
				{
					if(conjuntoJava.contains(nombre)) // nombre ya en el conjunto
						System.out.println("Error: " + nombre + " ya se agrego al conjunto de desarrolladores de Java\n");
						
					else
					{
						conjuntoJava.add(nombre); // se agrega el nombre al conjunto
						System.out.println(nombre + " fue agregado al conjunto de desarrolladores de Java");
					}
				}
				
				else if(option2.equals("2"))
				{
					if(conjuntoWeb.contains(nombre))
						System.out.println("Error: " + nombre + " ya se agrego al conjunto de desarrolladores de Web\n");
						
					else
					{
						conjuntoWeb.add(nombre);
						System.out.println(nombre + " fue agregado al conjunto de desarrolladores de Web");
					}
				}
				
				else if(option2.equals("3"))
				{
					if(conjuntoCel.contains(nombre))
						System.out.println("Error: " + nombre + " ya se agrego al conjunto de desarrolladores de Celulares\n");
						
					else
					{
						conjuntoCel.add(nombre);
						System.out.println(nombre + " fue agregado al conjunto de desarrolladores de Celulares");
					}
				}
				
				else if(option2.equals("4")) // para agregar otro nombre
					ciclo2 = false;
				
				else if(option2.equals("5")) // para dejar de agregar nombres 
				{
					ciclo = true;
					ciclo2 = false;
				}
				
				else
					System.out.println("Error: opcion invalida\n");
			}
		}
		
		// enteros Comparable que indican el numero de objetos en cada conjunto
		Integer javaSize = conjuntoJava.size();
		Integer webSize = conjuntoWeb.size();
		Integer celSize = conjuntoCel.size();			
		int largest = 1; // por default se supone que conjuntoWeb es el mayor
		
		if((webSize.compareTo(celSize) != -1) && (webSize.compareTo(javaSize) != -1))
			largest = 1; // conjuntoWeb tiene el mayor numero de objetos
			
		else if((javaSize.compareTo(webSize) != -1) && (javaSize.compareTo(celSize) != -1))
			largest = -1; // conjuntoJava tiene el mayor numero de objetos
			
		else
			largest = 0; // conjuntoCel tiene el mayor numero de objetos
	
		while(ciclo)
		{
			System.out.println("\n1.Ver interseccion de los tres conjuntos\n2.Ver desarrolladores con experiencia en Java pero no en Web");
			System.out.println("3.Ver interseccion de conjuntos de desarrolladores de Web y Celulares\n4.Ver union de Web y Celulares");
			System.out.println("5.Ver conjunto mas grande\n6.Ver conjunto mas grande (nombres ordenados)");
			System.out.println("7.El conjunto de desarrolladores de Java es subconjunto del conjunto de\n  desarrolladores de Web?\n8.Salir");
			System.out.print("Que desea hacer? ");
			String option3 = teclado.nextLine();
			
			if(option3.equals("1"))
			// se recorre el conjunto mas grande y se revisa que objetos estan contenidos
			// tambien en los otros dos conjuntos, y se muestran en pantalla
			{
				System.out.print("La interseccion de los tres conjuntos es:\n[");
			
				if(largest == -1)
				{
					for(String s : conjuntoJava)
						if(conjuntoWeb.contains(s) && conjuntoCel.contains(s))
							System.out.print(s + " " );
				}
				
				else if(largest == 0)
				{
					for(String s : conjuntoCel)
						if(conjuntoWeb.contains(s) && conjuntoJava.contains(s))
							System.out.print(s + " " );
				}
				
				else
				{
					for(String s : conjuntoWeb)
						if(conjuntoCel.contains(s) && conjuntoJava.contains(s))
							System.out.print(s + " " );
				}
				
				System.out.print("]\n");
			}
			
			else if(option3.equals("2"))
			// se recorre conjuntoJava y se muestran en pantalla los objetos que no esten contenidos
			// en conjuntoWeb
			{
				System.out.print("Los desarrolladores con experiencia en Java pero no en Web son:\n[");
				
				for(String s : conjuntoJava)
					if(!conjuntoWeb.contains(s))
						System.out.print(s + " ");
						
				System.out.print("]\n");
			}
			
			else if(option3.equals("3"))
			// se recorre conjuntoWeb para encontrar los objetos contenidos 
			// por conjuntoWeb y conjuntoCel, y se muestran en pantalla
			{
				System.out.print("La interseccion de desarrolladores de Web y Celulares es:\n[");
				
				for(String s : conjuntoWeb)
					if(conjuntoCel.contains(s))
						System.out.print(s + " ");
						
				System.out.print("]\n");
			}
			
			else if(option3.equals("4"))
			// se muestran todos los objetos contenidos por conjuntoWeb y conjuntoCel
			// y se evita mostrar el mismo objeto mas de una vez.
			{
				System.out.print("La union de los conjuntos de desarrolladores de Web y Celulares es:\n[");
				
				for(String s : conjuntoWeb)
					System.out.print(s + " ");
					
				for(String st : conjuntoCel)
					if(!conjuntoWeb.contains(st)) // si ya se mostro una vez, no se vuelve a mostrar
						System.out.print(st + " ");
					
				System.out.print("]\n");
			}
			
			else if(option3.equals("5"))
			// Se muestran todos los objetos del conjunto mas grande. Por default, 
			// se supone que el conjunto mas grande es conjuntoWeb y, si todos los 
			// conjuntos tienen la misma cantidad de objetos, se mostrara conjuntoWeb.
			{
				System.out.print("El conjunto mas grande es el conjunto de desarrolladores de ");
				
				// Para mostrar todos los objetos del conjunto apropiado, se usa un iterador.
				// Sin embargo, se podria recorrer tambien con un for.
				if(largest == -1)
				{
					System.out.print("Java\n[");
					Iterator<String> itr = conjuntoJava.iterator();
					
					while(itr.hasNext())
						System.out.print(itr.next() + " ");
						
					System.out.print("]\n");
				}
				
				else if(largest == 0)
				{
					System.out.print("Celular\n[");
					Iterator<String> itr = conjuntoCel.iterator();
					
					while(itr.hasNext())
						System.out.print(itr.next() + " ");
						
					System.out.print("]\n");
				}
				
				else
				{
					System.out.print("Web\n[");
					Iterator<String> itr = conjuntoWeb.iterator();
					
					while(itr.hasNext())
						System.out.print(itr.next() + " ");
						
					System.out.print("]\n");
				}
			}
			
			else if(option3.equals("6"))
			// Muestra el conjunto mas grande como en la opcion 5.
			// Sin embargo, el conjunto se copia a un Array de objetos
			// y se ordena con el metodo sort() que proporciona Java
			// Los objetos que se muestran ya ordenados son del Array.
			{
				System.out.print("El conjunto mas grande es el conjunto de desarrolladores de ");
				
				if(largest == -1)
				{
					System.out.print("Java\n[");
					Object[] javaArray = conjuntoJava.toArray(); // metodo de la interfaz Set
					java.util.Arrays.sort(javaArray);
					
					for(Object s : javaArray)
						System.out.print(s + " ");
						
					System.out.print("]\n");
				}
				
				else if(largest == 0)
				{
					System.out.print("Celular\n[");
					Object[] celArray = conjuntoCel.toArray();
					java.util.Arrays.sort(celArray);
					
					for(Object s : celArray)
						System.out.print(s + " ");
						
					System.out.print("]\n");
				}
				
				else
				{
					System.out.print("Web\n[");
					Object[] webArray = conjuntoWeb.toArray();
					java.util.Arrays.sort(webArray);
					
					for(Object s : webArray)
						System.out.print(s + " ");
						
					System.out.print("]\n");
				}
			}
			
			else if(option3.equals("7"))
			// Se decide si conjuntoJava es un subconjunto de conjuntoWeb.
			// Para esto se revisa si todos los objetos contenidos en conjuntoJava
			// estan contenidos por conjuntoWeb. De ser asi, si es un subconjunto.
			{
				int i = 0;
				
				for(String s : conjuntoJava)
					if(conjuntoWeb.contains(s))
						i++; // se incrementa un contador cada vez que un objeto de conjuntoJava este contenido en conjuntoWeb
						
				// se decide si conjuntoJava es un subconjunto por medio del contador
				if(i == conjuntoJava.size())
					System.out.println("El conjunto de desarrolladores de Java si es un subconjunto de desarrolladores\nde Web");
								
				else
					System.out.println("El conjunto de desarrolladores de Java no es un subconjunto de desarrolladores\nde Web");
			}
			
			else if(option3.equals("8")) // terminar el ciclo
				ciclo = false;
			
			else
				System.out.println("Error: opcion invalida");
		}
	}
}